-
Notifications
You must be signed in to change notification settings - Fork 33
Initial support for using Embassy with Rust on Zephyr #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Adds the Cargo.toml framework for initial support of using Embassy's executor on Zephyr. This implements a time driver for Embassy using a `k_timer` from Zephyr. Signed-off-by: David Brown <[email protected]>
This demo shows shows a few async tasks that are coordinated using the Embassy embassy-thread executor. Signed-off-by: David Brown <[email protected]>
This implements an executor for Embassy that runs a set of async tasks on a single Zephyr thread. The executor will suspend the thread when there is no work to do, resuming when there is work. It is permissible to run multiple executors, on different threads, to support a hybrid async cooperative and priority-based scheduling. Signed-off-by: David Brown <[email protected]>
Update the embassy demo to use the Zephyr executor. This performs a ping-ping test using two executors, with one end of the responder running on another thread. On the rp2040, the round trip time with `executor-threaded` is about 12us, with `executor-zephyr`, all on a single thread, it is about 15us, and with pairs of task running across differrent threads, the time is about 26us. Signed-off-by: David Brown <[email protected]>
Update the formatting. Signed-off-by: David Brown <[email protected]>
Run `cargo fmt`. Signed-off-by: David Brown <[email protected]>
Signed-off-by: David Brown <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running embassy on Zephyr wasn't on my 2025 bingo sheet, but I have to say this is really quite cool.
I wonder how this might work if you want to run the full embassy network stack in place of Zephyrs for example, where security might be a real honest to goodness concern and Rust would likely help. I kind of love the possibilities this opens up.
Or given a user mode thread could multiple embassy executors in some manner be sandboxed? Clearly accessing the hardware in a fine grained manner would need some thinking on that front.
@teburd a couple of thoughts: As far as using parts of Embassy instead of Rust. The main challenge here is hooking the device interrupts in so that the call into the hal. Since for most things in the hal, embassy requires this to be done by hand, this shouldn't be all that difficult. But, the mechanisms are very different, and Zephyr is going to need the irqs to still go through it's irq handling, as this will be needed in order for an irq to be able to cause the Zephyr scheduler to do something. Otherwise, I would think it would then mostly just be an issue of disabling that functionality on the Zephyr side. Running a mix of these shouldn't be all that difficult. As far as user mode goes, getting all of the permissions working would probably be a bit hard, especially since the hal is going to want access to hardware blocks. If there are enough MPU regions, this is probably doable, although it is a little unclear how user mode will help rust code, as it is largely redundant. It almost seems like more useful would be to have the userspace used to protect the rest of the system from some block of C code. |
On 64-bit targets, the task Futures are larger, and the chosen pool size is not adequate. Increase to 2k, which still should fit in the memory constraints on all targets, but not just fail immediately on 64-bit targets. Signed-off-by: David Brown <[email protected]>
Print a message after the test finish, and use this to terminate the tests with success. Signed-off-by: David Brown <[email protected]>
With the directives themselves removed, remove the import to avoid a warning about unused imports. Signed-off-by: David Brown <[email protected]>
Clippy complains about a no-argument `new()` method without an accompanying Default. It doesn't hurt anything to add, and could make this potentially slightly more useful. Signed-off-by: David Brown <[email protected]>
These changes add the ability to use the executor from Embassy on Zephyr. For the most part, Embassy's executor and associated utilities (embassy-time, embassy-sync, embassy-futures) are fairly platform agnostic. This support adds the two things needed to make this all work on Zephyr:
embassy-timer-driver
, so that all of the time related utilities fromembassy-time
work. There is a bit of challenge here as the embassy utilities expect the tick rate to be set via a feature, and in Zephyr this comes through Kconfig. But, once set correctly, the result should be seamless.Executor
that works just likeembassy-executor
's built in Executor type, except that it is intended to be run on a single Zephyr thread. More than one Executor can be run, each on its own thread, to provide a useful compromise between the lower-overhead scheduling of an executor, and priority-based scheduling that comes from using multiple threads.Some simple benchmarking shows the following. All of these are measuring the round trip time between two async tasks sending a single message over a channel, and a result back.
executor-thread
executor that expects to be running on the single lowest priority thread.executor-zephyr
executor, with all of the async tasks scheduled on a single executor. This includes the above switch time, along with a little overhead needed to support Zephyr threads.executor-zephyr
executor, with one task of the pair running on a separate thread. This includes the zephyr context switch time in with the executor switch time.All of these scenarios are useful in different situations.